// Copyright 2022 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package protowalk contains routines for efficiently walking proto messages,
// focusing on the ability to react to field annotations.
//
// This package defines an interface (FieldProcessor) which you can
// implement to react to any fields you like.
//
// This package also comes with stock implementations for the following common
// field annotations:
//   - google.api.field_behavior = REQUIRED
//   - google.api.field_behavior = OUTPUT_ONLY
//   - deprecated = true
//
// # How it works
//
// 1. Construct a new `Walker`
//
// Call [NewWalker][*YourProtoMessage](processors...) to get a new [Walker[M]]
// instance. This computes an execution plan to quickly check instances of
// M for any fields which need processing according to `processors`. You should
// make this Walker[M] at `init()` time, or similar, to avoid paying the
// plan computation cost multiple times.
//
// 2. Use [Walker.Execute]() with an instance of *YourProtoMessage.
//
// This will efficiently walk over the actual instance, checking just the fields
// which any of the given processors indicated needed processing.
//
// The upshot is that Walker.Execute() should be O(CheckableFields), no matter
// how big the proto messages are, rather than a naive O(Fields) implementation.
// Note that if the checkable field is in a repeated message or similar, that
// the processors will be called once per instance of this checkable field, so
// it is still possible for an incoming request message to cause variable amounts
// of processing work.
//
// The returned Result contains the ProtoPath and a message generated by the
// FieldProcessor. The ProtoPath describes the path through the source message
// to the affected field, and can either be printed for display, or can be used
// to retrieve the actual value.
package protowalk
